package com.may.module.security.config;

import com.may.module.security.entity.PermissionEntity;
import com.may.module.security.filter.JwtTokenFilter;
import com.may.module.security.mapper.PermissionMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCrypt;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import java.util.List;

/**
 * @author May
 * @date 2021/08/03 12:25
 */
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private PermissionMapper permissionMapper;
    @Autowired
    private UserDetailsService userDetailsService;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // httpBasic模式
        // http.authorizeRequests().antMatchers("/**").fullyAuthenticated().and().httpBasic();
        // formLogin模式
//         http.authorizeRequests().antMatchers("/**").fullyAuthenticated().and().formLogin();
//         http.authorizeRequests().antMatchers("/addUser").hasAnyAuthority("addUser")
//                 .antMatchers("/delUser").hasAnyAuthority("delUser")
//                 .antMatchers("/updateUser").hasAnyAuthority("updateUser")
//                 .antMatchers("/showUser").hasAnyAuthority("showUser")
//                 .antMatchers("/**").fullyAuthenticated()
//                 .and()
//                 .formLogin();
        ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry authorizeRequests =
                http.authorizeRequests();
        // 查询所有权限
        List<PermissionEntity> allPermission = permissionMapper.findAllPermission();
        // 添加拦截规则
        allPermission.forEach(p -> authorizeRequests.antMatchers(p.getUrl()).hasAnyAuthority(p.getPermTag()));
        // 放行登陆
        authorizeRequests.antMatchers("/login").permitAll()
                // 拦截所有
                .antMatchers("/**").fullyAuthenticated()
                .and()
                .csrf().disable()
                //因为使用JWT，所以不需要HttpSession
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .logout().logoutUrl("/logout");
        //使用自定义的 Token过滤器 验证请求的Token是否合法
        http.addFilterBefore(authenticationTokenFilterBean(), UsernamePasswordAuthenticationFilter.class);
        http.headers().cacheControl();

    }

    @Bean
    public JwtTokenFilter authenticationTokenFilterBean() throws Exception {
        return new JwtTokenFilter();
    }

    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        // auth.inMemoryAuthentication().withUser("admin").password("123456").authorities("addUser", "delUser",
        //         "updateUser", "showUser");
//         auth.inMemoryAuthentication().withUser("add").password("123456").authorities("addUser");
        // auth.inMemoryAuthentication().withUser("update").password("123456").authorities("updateUser");
        // auth.inMemoryAuthentication().withUser("del").password("123456").authorities("delUser");
        auth.userDetailsService(userDetailsService).passwordEncoder(new PasswordEncoder() {
            @Override
            public String encode(CharSequence rawPassword) {
                return passwordEncoder().encode(rawPassword);
            }

            @Override
            public boolean matches(CharSequence rawPassword, String encodedPassword) {
                return BCrypt.checkpw(rawPassword.toString(), encodedPassword);
            }
        });
    }

//     @Bean
//     public static NoOpPasswordEncoder passwordEncoder() {
//         return (NoOpPasswordEncoder) NoOpPasswordEncoder.getInstance();
//     }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}
